// Description: 描述
package tools

import (
	"reflect"
	"time"
	"unsafe"

	"github.com/shopspring/decimal"
)

// BirthdayToAge 生日转年龄
func BirthdayToAge(birthday string, layout ...string) (age int64, err error) {
	defaultLayout := "2006-01-02"
	if len(layout) > 0 {
		defaultLayout = layout[0]
	}

	t, err := time.Parse(defaultLayout, birthday)
	if err != nil {
		return 0, err
	}

	age = int64(time.Now().Year() - t.Year())
	if int(time.Now().Month()) < int(t.Month()) {
		age--
	}

	return
}

// BirthdayToConstellation 生日转星座
func BirthdayToConstellation(birthday string) string {
	localTime, convertErr := time.ParseInLocation("2006-01-02", birthday, time.Local)
	if convertErr != nil {
		return "未知"
	}

	month, day := int(localTime.Month()), localTime.Day()
	var star string
	switch {
	case month == 1 && day >= 20, month == 2 && day <= 18:
		star = "水瓶座"
	case month == 2 && day >= 19, month == 3 && day <= 20:
		star = "双鱼座"
	case month == 3 && day >= 21, month == 4 && day <= 19:
		star = "白羊座"
	case month == 4 && day >= 20, month == 5 && day <= 20:
		star = "金牛座"
	case month == 5 && day >= 21, month == 6 && day <= 21:
		star = "双子座"
	case month == 6 && day >= 22, month == 7 && day <= 22:
		star = "巨蟹座"
	case month == 7 && day >= 23, month == 8 && day <= 22:
		star = "狮子座"
	case month == 8 && day >= 23, month == 9 && day <= 22:
		star = "处女座"
	case month == 9 && day >= 23, month == 10 && day <= 22:
		star = "天秤座"
	case month == 10 && day >= 23, month == 11 && day <= 21:
		star = "天蝎座"
	case month == 11 && day >= 22, month == 12 && day <= 21:
		star = "射手座"
	case month == 12 && day >= 22, month == 1 && day <= 19:
		star = "摩羯座"
	}

	return star
}

func StrToBytes(s string) []byte {
	stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))

	var b []byte
	pBytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	pBytes.Data = stringHeader.Data
	pBytes.Len = stringHeader.Len
	pBytes.Cap = stringHeader.Len

	return b
}

func BytesToStr(b []byte) string {
	bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))

	var s string
	pStr := (*reflect.StringHeader)(unsafe.Pointer(&s))
	pStr.Data = bytesHeader.Data
	pStr.Len = bytesHeader.Len

	return s
}

// Cent2Yuan 分转元
// 除100 把分转成元，转换后的结果包含整数和小数部分
func Cent2Yuan(cent int64) (yuan float64) {
	yuan, _ = decimal.NewFromInt(cent).DivRound(decimal.NewFromInt(100), 2).Float64()
	return
}

// YuanStr2Cent 元(字符串)转分
// 乘100把元转为分，转换后整数部分即为分，小数部分为分之后的单位可忽略
func YuanStr2Cent(yuan string) (cent int64, err error) {
	d, err := decimal.NewFromString(yuan)
	if err != nil {
		return
	}
	return d.Mul(decimal.NewFromInt(100)).IntPart(), nil
}

// Yuan2Cent 元转分
// 乘100把元转为分，转换后整数部分即为分，小数部分为分之后的单位可忽略
func Yuan2Cent(yuan float64) (cent int64) {
	return decimal.NewFromFloat(yuan).Mul(decimal.NewFromInt(100)).IntPart()
}

// Int64Pointer 获取int64指针
func Int64Pointer(i int64) *int64 {
	return &i
}

// BoolPointer 获取bool指针
func BoolPointer(i bool) *bool {
	return &i
}
